package com.etop.weiway.wxmanage.service;

import com.etop.weiway.basic.service.BaseService;
import com.etop.weiway.commons.web.Pager;
import com.etop.weiway.wxmanage.dao.AccountDAO;
import com.etop.weiway.wxmanage.dao.WeixinUserDAO;
import com.etop.weiway.wxmanage.dao.WeixinUserGroupDAO;
import com.etop.weiway.wxmanage.entity.Account;
import com.etop.weiway.wxmanage.entity.WeixinUser;
import com.etop.weiway.wxmanage.entity.WeixinUserGroup;
import com.etop.weiway.wxmanage.util.WeixinTimeUtil;
import com.etop.weixin.entity.advanced.WxUser;
import com.etop.weixin.utils.WxUserUtil;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * 微信用户服务
 * Created by KyLeo on 2015/1/15.
 */
@Service("WxUserService")
public class WxUserManageService extends BaseService {
    @Autowired
    private WeixinUserDAO weixinUserDAO;
    @Autowired
    private WeixinUserGroupDAO weixinUserGroupDAO;
    @Autowired
    private AccountService accountService;

    /**
     * 保存用户的注册信息(真实姓名、联系号码)
     *
     * @param weixinUser
     */
    public void saveRegisterInfo(WeixinUser weixinUser, WeixinUser oldUser) throws Exception {
        log.debug("********************保存用户的注册信息************************");
        oldUser.setRealname(weixinUser.getRealname());
        oldUser.setPhoneNumber(weixinUser.getPhoneNumber());
        weixinUserDAO.update(oldUser);
    }

    /**
     * 同步微信用户
     * 对于已存在的用户，更新其资料和置valid为1
     * 对于不存在的用户，直接保存
     *
     * @param account
     * @throws Exception
     */
    public void saveWxUserList(Account account) throws Exception {
        log.debug("*******************************同步微信用户*****************************");
        //目前通过该途径获取accessToken，有潜在风险，假如在有效时间内不能完成所有数据的同步的话
        String accessToken = WeixinTimeUtil.getAccessToken(account);
        List<String> wxUserList = WxUserUtil.getAllUserId(accessToken, null);
        if (wxUserList != null && !wxUserList.isEmpty()) {
            this.deleteAllWxUserByAccountId(account.getId());
            Iterator<String> iterator = wxUserList.iterator();
            while (iterator.hasNext()) {
                String openId = iterator.next();
                //暂时采用每次查询用户详细资料时，重新获取accessToken的方法来规避这个问题
                WxUser wxUser = WxUserUtil.getUserInfo(WeixinTimeUtil.getAccessToken(account), openId);
                WeixinUser weixinUser = this.findWxUser(account.getId(), openId);
                this.saveOrUpdateWeixinUserInfo(weixinUser, wxUser, account, openId);
            }
        } else {
            throw new Exception("从微信服务器获取用户数据失败!");
        }
    }

    /**
     * 用户关注微信号的时候，保存或者更新微信用户的个人信息
     *
     * @param wechatId
     * @param openId
     * @throws Exception
     */
    public void saveOrUpdateWxUser(String wechatId, String openId) {
        log.debug("**************保存或者更新微信用户的个人信息****************");
        Account account = null;
        String accessToken = null;
        try {
            account = accountService.loadAccountByWechatId(wechatId);
            accessToken = WeixinTimeUtil.getAccessToken(account);

            WxUser wxUser = WxUserUtil.getUserInfo(accessToken, openId);
            WeixinUser weixinUser = this.findWxUser(account.getId(), openId);
            log.info("从微信获取到的用户的昵称是 : " + wxUser.getNickname());

            this.saveOrUpdateWeixinUserInfo(weixinUser, wxUser, account, openId);
        } catch (Exception e) {
            log.debug(e);
        }
    }

    /**
     * 把对应公众号下面的所有微信用户valid置0
     *
     * @param accountId
     */
    public void deleteAllWxUserByAccountId(Integer accountId) {
        log.debug("*******************把对应公众号下面的所有微信用户valid置0*************************");
        Map<String, Object> params = createParamMap();
        params.put("accountId", accountId);
        String strQuery = "update WeixinUser t set t.valid = 0 where t.account.id = :accountId";
        weixinUserDAO.excute(strQuery, params);
    }

    /**
     * 保存或者更新微信用户资料
     *
     * @param weixinUser
     * @param wxUser
     * @param account
     * @param openId
     */
    public void saveOrUpdateWeixinUserInfo(WeixinUser weixinUser, WxUser wxUser, Account account, String openId) {
        weixinUser.setAccount(account);
        weixinUser.setOpenId(openId);
        weixinUser.setSubscribe(wxUser.getSubscribe());
        weixinUser.setNickname(wxUser.getNickname());
        //weixinUser.setGroup(null);
        //weixinUser.setRealname(null);
        //weixinUser.setPhoneNumber(null);
        weixinUser.setSex(wxUser.getSex());
        weixinUser.setCity(wxUser.getCity());
        weixinUser.setCountry(wxUser.getCountry());
        weixinUser.setProvince(wxUser.getProvince());
        weixinUser.setLanguage(wxUser.getLanguage());
        weixinUser.setHeadimgurl(wxUser.getHeadimgurl());
        weixinUser.setSubscribeTime(Long.parseLong(wxUser.getSubscribe_time()));
        weixinUser.setUnionid(wxUser.getUnionid());
        weixinUser.setValid(new Short("1"));

        weixinUserDAO.saveOrUpdate(weixinUser);
    }

    /**
     * 根据公众号ID和openId来查找微信用户
     *
     * @param accountId
     * @param openId
     * @return
     */
    public WeixinUser findWxUser(Integer accountId, String openId) {
        log.debug("*******************根据公众号ID和openId来查找微信用户*************************");
        Map<String, Object> params = createParamMap();
        params.put("accountId", accountId);
        params.put("openId", openId);
        String strQuery = "from WeixinUser t where t.account.id = :accountId and t.openId = :openId";
        List<WeixinUser> list = weixinUserDAO.find(strQuery, params);
        log.info("查询到的用户数量为：" + list.size());
        return list.size() > 0 ? list.get(0) : new WeixinUser();
    }

    /**
     * 用户取消关注的时候，删除数据库对应的用户记录(valid字段置0和groupId置空)
     *
     * @param wechatId
     * @param openId
     * @throws Exception
     */
    public void deleteWxUser(String wechatId, String openId) {
        log.debug("**************删除微信用户的个人信息****************");
        Account account = null;
        try {
            account = accountService.loadAccountByWechatId(wechatId);
        } catch (Exception e) {
            log.debug(e);
        }
        Map<String, Object> params = createParamMap();
        params.put("openId", openId);
        params.put("accountId", account.getId());
        params.put("group", null);
        String queryString = "update WeixinUser t set t.valid = 0, t.group = :group where t.valid = 1 and t.openId = :openId and t.account.id = :accountId";
        weixinUserDAO.excute(queryString, params);
    }

    /**
     * 根据公众号ID和分组ID获取微信用户列表
     *
     * @param pager
     * @param accountId
     * @param keyword
     * @param groupId
     * @return
     */
    public Pager<WeixinUser> getWxUserListByAccountId(Pager<WeixinUser> pager, Integer accountId, String keyword, String groupId) throws Exception {
        log.debug("*******************根据公众号ID和分组ID获取微信用户列表*************************");
        Map<String, Object> params = createParamMap();
        params.put("accountId", accountId);
        String queryString = "from WeixinUser t where t.valid = 1 and t.account.id = :accountId";

        if (!StringUtils.isEmpty(keyword)) {
            queryString += " and (t.nickname like :keyword or t.realname like :keyword)";
            params.put("keyword", getKeyWords(keyword));
        }
        if (!StringUtils.isEmpty(groupId) && !"0".equals(groupId)) {
            queryString += " and t.group.id = :groupId";
            params.put("groupId", Integer.parseInt(groupId));
        } else {
            if ("0".equals(groupId)) {
                queryString += " and t.group.id is null";
            }
        }

        List<WeixinUser> list = weixinUserDAO.find(queryString, params, (pager.getPageNo() - 1) * pager.getPageSize(), pager.getPageSize());
        pager.setCount(weixinUserDAO.getTotalCount(queryString, params));
        pager.setList(list);
        return pager;
    }

    /**
     * 根据当前公众号获取微信用户分组
     *
     * @param accountId
     * @return
     */
    public List<Object> getWeixinUserGroupByAccountId(Integer accountId) throws Exception {
        log.debug("*******************根据当前公众号获取微信用户分组***********************");
        List<Object> groups = new ArrayList<>();
        Map<String, Object> params = createParamMap();
        params.put("accountId", accountId);

        String strAllUserQuery = "from WeixinUser t where t.account.id = :accountId and t.valid = 1";
        String strUnGroupUserQuery = strAllUserQuery + " and t.group.id is null";
        //String strGroupUserQuery = "select t from WeixinUserGroup t left  join t.weixinUsers u with u.valid > 0 where t.account.id =:accountId and t.valid = 1";
        String strGroupUserQuery = "select t,count(u) from WeixinUserGroup t left join t.weixinUsers u with u.valid = 1" +
                " where t.account.id =:accountId and t.valid = 1 group by t";
        int allUserAmount = weixinUserDAO.getTotalCount(strAllUserQuery, params);
        int unGroupUserAmount = weixinUserDAO.getTotalCount(strUnGroupUserQuery, params);
        List<WeixinUserGroup> groupList = this.getGroupListByAccountId(accountId);

        log.info("所有用户数为：" + allUserAmount);
        log.info("未分组用户数为：" + unGroupUserAmount);
        log.info("自定义的组别数目为：" + groupList.size());

        groups.add(allUserAmount);
        groups.add(unGroupUserAmount);
        groups.add(groupList);
        return groups;
    }

    /**
     * 更改用户所属组
     *
     * @param groupId
     * @param userId
     */
    public void updateUserGroup(String groupId, String userId) {
        log.debug("*******************更改用户所属组*************************");
        Map<String, Object> params = createParamMap();
        params.put("groupId", "0".equals(groupId) ? null : Integer.parseInt(groupId));
        params.put("userId", Integer.parseInt(userId));
        String strQuery = "update WeixinUser t set t.group.id = :groupId where t.id = :userId";
        weixinUserDAO.excute(strQuery, params);
    }

    /**
     * 批量更改用户所属组
     *
     * @param groupId
     * @param userSet
     */
    public void updateUserGroupBatch(String groupId, String userSet) {
        log.debug("*******************批量更改用户所属组*************************");
        if (!StringUtils.isEmpty(userSet) && !StringUtils.isEmpty(groupId)) {
            System.out.println(userSet);
            String[] wxUsers = userSet.split(",");
            for (String user : wxUsers) {
                System.out.println(user);
                updateUserGroup(groupId, user);
            }
        }
    }

    /**
     * 根据当前公众号获取所有分组
     *
     * @param accountId
     * @return
     * @throws Exception
     */
    public List<WeixinUserGroup> getGroupListByAccountId(Integer accountId) throws Exception {
        log.debug("**********************根据当前公众号获取所有分组**************************");
        Map<String, Object> params = createParamMap();
        List<WeixinUserGroup> gList = new ArrayList<>();
        params.put("accountId", accountId);
        String strQuery = "select t,count(u) from WeixinUserGroup t left join t.weixinUsers u with u.valid = 1" +
                " where t.account.id =:accountId and t.valid = 1 group by t";
        List<Object[]> groupList = weixinUserGroupDAO.findWithSelect(strQuery, params);

        //把用户数目保存进非持久化count字段中
        for (Object[] obj : groupList) {
            WeixinUserGroup group = (WeixinUserGroup) obj[0];
            Integer count = ((Long) obj[1]).intValue();
            group.setCount(count);
            gList.add(group);
        }

        return gList;
    }

    /**
     * 更新组
     *
     * @param groupId
     * @param groupName
     */
    public void updateGroup(String groupId, String groupName) {
        log.debug("***********************更新组*************************");
        WeixinUserGroup group = weixinUserGroupDAO.get(Integer.parseInt(groupId));
        group.setName(groupName);
        weixinUserGroupDAO.update(group);
    }

    /**
     * 添加组
     *
     * @param groupName
     * @param accountId
     */
    public void saveGroup(String groupName, Integer accountId) {
        log.debug("***********************添加组*************************");
        Account account = new Account();
        account.setId(accountId);

        WeixinUserGroup group = new WeixinUserGroup();
        group.setName(groupName);
        group.setAccount(account);
        group.setValid(new Short("1"));

        weixinUserGroupDAO.save(group);
    }

    /**
     * 删除组
     *
     * @param groupId
     */
    public void deleteGroup(String groupId) {
        log.debug("***********************删除组*************************");

        //有一种情况，用户的valid字段置为0，但是他还拥有分组，故需要对这种无效用户的组id置为空
        Map<String, Object> params = createParamMap();
        params.put("groupId", Integer.parseInt(groupId));
        String strQuery = "update WeixinUser t set t.group = null where t.group.id = :groupId and t.valid = 0";
        weixinUserDAO.excute(strQuery, params);

        //删除组
        weixinUserGroupDAO.deleteById(Integer.parseInt(groupId));
    }

    /**
     * 判断用户是否注册真实姓名和手机号码
     *
     * @param accountId
     * @param openId
     * @return
     * @throws Exception
     */
    public boolean isRegistered(Integer accountId, String openId) throws Exception {
        log.debug("**********************判断用户是否注册真实姓名和手机号码****************************");
        WeixinUser weixinUser = this.findWxUser(accountId, openId);
        if (weixinUser.getRealname() != null && !"".equals(weixinUser.getRealname())
                && weixinUser.getPhoneNumber() != null && !"".equals(weixinUser.getPhoneNumber())) {
            return true;
        } else {
            return false;
        }
    }
}
